package user

import (
	"errors"
	"x-admin/backend/pkg/utils"

	"gorm.io/gorm"
)

// Service 用户业务逻辑层接口
type Service interface {
	Create(req *CreateRequest) (*UserWithRoles, error)
	GetByID(id uint) (*UserWithRoles, error)
	Update(id uint, req *UpdateRequest) (*UserWithRoles, error)
	Delete(id uint) error
	List(req *QueryRequest) ([]*UserWithRoles, int64, error)
	ResetPassword(id uint, req *ResetPasswordRequest) error
}

// service 用户业务逻辑层实现
type service struct {
	repo Repository
}

// NewService 创建用户业务逻辑层
func NewService(repo Repository) Service {
	return &service{
		repo: repo,
	}
}

// Create 创建用户
func (s *service) Create(req *CreateRequest) (*UserWithRoles, error) {
	// 检查用户名是否已存在
	if _, err := s.repo.GetByUsername(req.Username); err == nil {
		return nil, errors.New("用户名已存在")
	}

	// 检查邮箱是否已存在（仅当邮箱不为空时检查）
	if req.Email != "" {
		if _, err := s.repo.GetByEmail(req.Email); err == nil {
			return nil, errors.New("邮箱已存在")
		}
	}

	// 加密密码
	hashedPassword, err := utils.HashPassword(req.Password)
	if err != nil {
		return nil, errors.New("密码加密失败")
	}

	// 设置默认状态
	status := 1
	if req.Status != nil {
		status = *req.Status
	}

	user := &User{
		Username: req.Username,
		Nickname: req.Nickname,
		Email:    req.Email,
		Phone:    req.Phone,
		Password: hashedPassword,
		Avatar:   req.Avatar,
		Status:   status,
	}

	// 创建用户
	if err := s.repo.Create(user); err != nil {
		return nil, err
	}

	// 更新用户角色
	if len(req.RoleIDs) > 0 {
		if err := s.repo.UpdateRoles(user.ID, req.RoleIDs); err != nil {
			return nil, errors.New("角色分配失败")
		}
	}

	// 返回带角色信息的用户
	return s.repo.GetUserWithRoles(user.ID)
}

// GetByID 根据ID获取用户
func (s *service) GetByID(id uint) (*UserWithRoles, error) {
	user, err := s.repo.GetUserWithRoles(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户不存在")
		}
		return nil, err
	}
	return user, nil
}

// Update 更新用户
func (s *service) Update(id uint, req *UpdateRequest) (*UserWithRoles, error) {
	user, err := s.repo.GetByID(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户不存在")
		}
		return nil, err
	}

	// 更新字段
	if req.Username != nil {
		// 检查用户名是否已被其他用户使用
		if existingUser, err := s.repo.GetByUsername(*req.Username); err == nil && existingUser.ID != id {
			return nil, errors.New("用户名已存在")
		}
		user.Username = *req.Username
	}

	if req.Nickname != nil {
		user.Nickname = *req.Nickname
	}

	if req.Phone != nil {
		user.Phone = *req.Phone
	}

	if req.Email != nil {
		// 检查邮箱是否已被其他用户使用（仅当邮箱不为空时检查）
		if *req.Email != "" {
			if existingUser, err := s.repo.GetByEmail(*req.Email); err == nil && existingUser.ID != id {
				return nil, errors.New("邮箱已存在")
			}
		}
		user.Email = *req.Email
	}

	if req.Password != nil {
		hashedPassword, err := utils.HashPassword(*req.Password)
		if err != nil {
			return nil, errors.New("密码加密失败")
		}
		user.Password = hashedPassword
	}

	if req.Avatar != nil {
		user.Avatar = *req.Avatar
	}

	if req.Status != nil {
		user.Status = *req.Status
	}

	// 更新用户信息
	if err := s.repo.Update(user); err != nil {
		return nil, err
	}

	// 更新用户角色
	if req.RoleIDs != nil {
		if err := s.repo.UpdateRoles(user.ID, req.RoleIDs); err != nil {
			return nil, errors.New("角色更新失败")
		}
	}

	// 返回更新后的用户信息
	return s.repo.GetUserWithRoles(user.ID)
}

// Delete 删除用户
func (s *service) Delete(id uint) error {
	user, err := s.repo.GetByID(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("用户不存在")
		}
		return err
	}

	return s.repo.Delete(user.ID)
}

// List 获取用户列表
func (s *service) List(req *QueryRequest) ([]*UserWithRoles, int64, error) {
	// 设置默认分页参数
	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}
	if req.PageSize > 100 {
		req.PageSize = 100
	}

	return s.repo.List(req)
}

// ResetPassword 重置密码
func (s *service) ResetPassword(id uint, req *ResetPasswordRequest) error {
	user, err := s.repo.GetByID(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("用户不存在")
		}
		return err
	}

	// 加密新密码
	hashedPassword, err := utils.HashPassword(req.NewPassword)
	if err != nil {
		return errors.New("密码加密失败")
	}

	user.Password = hashedPassword
	return s.repo.Update(user)
}
